<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>JSON转JS对象工具</title>
  <style>
      * {
          box-sizing: border-box;
          margin: 0;
          padding: 0;
      }

      body {
          font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
          line-height: 1.6;
          color: #333;
          background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
          padding: 20px;
          min-height: 100vh;
      }

      .container {
          max-width: 1200px;
          margin: 0 auto;
          background: white;
          border-radius: 12px;
          box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
          overflow: hidden;
      }

      header {
          background: #4a6bdf;
          color: white;
          padding: 20px;
          text-align: center;
      }

      h1 {
          font-size: 2.2rem;
          margin-bottom: 10px;
      }

      .description {
          font-size: 1.1rem;
          opacity: 0.9;
          max-width: 800px;
          margin: 0 auto;
      }

      .main-content {
          display: flex;
          flex-wrap: wrap;
          padding: 20px;
          gap: 20px;
      }

      .input-section, .output-section {
          flex: 1;
          min-width: 300px;
      }

      .section-header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-bottom: 10px;
      }

      h2 {
          font-size: 1.5rem;
          color: #4a6bdf;
      }

      .button {
          background: #4a6bdf;
          color: white;
          border: none;
          padding: 8px 16px;
          border-radius: 4px;
          cursor: pointer;
          font-size: 0.9rem;
          transition: background 0.3s;
      }

      .button:hover {
          background: #3a5bc7;
      }

      textarea {
          width: 100%;
          height: calc(100vh - 340px);
          padding: 15px;
          border: 1px solid #ddd;
          border-radius: 8px;
          font-family: 'Consolas', 'Monaco', monospace;
          font-size: 14px;
          line-height: 1.5;
          resize: vertical;
          box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
      }

      .output {
          width: 100%;
          height: calc(100vh - 340px);
          padding: 15px;
          border: 1px solid #ddd;
          border-radius: 8px;
          background: #f8f9fa;
          overflow: auto;
          white-space: pre;
          font-family: 'Consolas', 'Monaco', monospace;
          font-size: 14px;
          line-height: 1.5;
          box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
      }

      .error {
          color: #e74c3c;
          margin-top: 10px;
          padding: 10px;
          border-radius: 4px;
          background: #fde8e6;
          font-size: 0.9rem;
      }

      .success {
          color: #2ecc71;
          margin-top: 10px;
          padding: 10px;
          border-radius: 4px;
          background: #e8f6ef;
          font-size: 0.9rem;
          text-align: center;
      }

      .actions {
          display: flex;
          justify-content: space-between;
          margin-top: 20px;
          gap: 10px;
      }

      .action-button {
          flex: 1;
          padding: 12px;
          font-size: 1rem;
      }

      @media (max-width: 768px) {
          .main-content {
              flex-direction: column;
          }
      }

      .property {
          color: #905;
      }

      .string {
          color: #690;
      }

      .number {
          color: #905;
      }

      .boolean {
          color: #07a;
      }

      .null {
          color: #07a;
      }

      .copy-notification {
          position: fixed;
          top: 20px;
          left: 50%;
          transform: translateX(-50%);
          background: #2ecc71;
          color: white;
          padding: 10px 20px;
          border-radius: 4px;
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
          z-index: 1000;
          opacity: 0;
          transition: opacity 0.3s;
      }

      .copy-notification.show {
          opacity: 1;
      }
  </style>
</head>
<body>
<div class="container">
  <header>
    <h1>JSON转JS对象工具</h1>
    <p class="description">将JSON格式数据转换为JavaScript对象格式，自动去掉键的引号并格式化输出</p>
  </header>

  <div class="main-content">
    <div class="input-section">
      <div class="section-header">
        <h2>JSON输入</h2>
        <button id="example-btn" class="button">示例数据</button>
      </div>
      <textarea id="json-input"
                placeholder='请输入JSON数据，例如：{"name": "John", "age": 30, "isStudent": false}'></textarea>
      <div id="input-error" class="error" style="display: none;"></div>
    </div>

    <div class="output-section">
      <div class="section-header">
        <h2>JS对象输出</h2>
        <button id="copy-btn" class="button">复制结果</button>
      </div>
      <pre id="js-output" class="output"></pre>
    </div>
  </div>

  <div class="actions">
    <button id="clear-btn" class="button action-button">清除</button>
    <button id="convert-btn" class="button action-button">转换</button>
  </div>

</div>

<div id="copy-notification" class="copy-notification">已成功复制到剪贴板！</div>

<script>
  document.addEventListener('DOMContentLoaded', function () {
    const jsonInput = document.getElementById('json-input');
    const jsOutput = document.getElementById('js-output');
    const convertBtn = document.getElementById('convert-btn');
    const clearBtn = document.getElementById('clear-btn');
    const exampleBtn = document.getElementById('example-btn');
    const copyBtn = document.getElementById('copy-btn');
    const inputError = document.getElementById('input-error');
    const copyNotification = document.getElementById('copy-notification');

    // 示例JSON数据
    const exampleJSON = `{
    "name": "John Doe",
    "age": 30,
    "isStudent": false,
    "hobbies": ["reading", "traveling", "coding"],
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "country": "USA"
    },
    "scores": [95, 89, 78],
    "profile": null
}`;

    // 显示示例数据
    exampleBtn.addEventListener('click', function () {
      jsonInput.value = exampleJSON;
      convertJSON();
    });

    // 转换功能
    convertBtn.addEventListener('click', convertJSON);

    // 实时转换（输入时）
    jsonInput.addEventListener('input', function () {
      convertJSON();
    });

    // 清除功能
    clearBtn.addEventListener('click', function () {
      jsonInput.value = '';
      jsOutput.textContent = '';
      inputError.style.display = 'none';
    });

    // 复制功能
    copyBtn.addEventListener('click', function () {
      if (jsOutput.textContent) {
        // 创建一个临时的textarea元素来复制文本
        const tempTextArea = document.createElement('textarea');
        tempTextArea.value = jsOutput.textContent;
        document.body.appendChild(tempTextArea);
        tempTextArea.select();

        try {
          const successful = document.execCommand('copy');
          if (successful) {
            showCopyNotification();
          } else {
            console.error('复制失败');
          }
        } catch (err) {
          console.error('复制错误:', err);
        }

        document.body.removeChild(tempTextArea);
      }
    });

    // 显示复制成功通知
    function showCopyNotification() {
      copyNotification.classList.add('show');
      setTimeout(() => {
        copyNotification.classList.remove('show');
      }, 2000);
    }

    // JSON转换函数
    function convertJSON() {
      const jsonString = jsonInput.value.trim();
      inputError.style.display = 'none';

      if (!jsonString) {
        jsOutput.textContent = '';
        return;
      }

      try {
        // 解析JSON
        const jsonObject = JSON.parse(jsonString);

        // 转换为JS对象字符串并高亮显示
        const jsObjectString = objectToJSString(jsonObject);
        jsOutput.innerHTML = jsObjectString;

      } catch (error) {
        inputError.textContent = `JSON格式错误: ${error.message}`;
        inputError.style.display = 'block';
        jsOutput.textContent = '';
      }
    }

    // 将对象转换为格式化的JS对象字符串并添加语法高亮
    function objectToJSString(obj, indent = 0) {
      if (obj === null) {
        return '<span class="null">null</span>';
      }

      if (typeof obj !== 'object') {
        if (typeof obj === 'string') {
          return `<span class="string">"${escapeHtml(obj)}"</span>`;
        }
        if (typeof obj === 'number') {
          return `<span class="number">${obj}</span>`;
        }
        if (typeof obj === 'boolean') {
          return `<span class="boolean">${obj}</span>`;
        }
        return obj;
      }

      if (Array.isArray(obj)) {
        if (obj.length === 0) {
          return '[]';
        }

        let result = '[\n';
        for (let i = 0; i < obj.length; i++) {
          result += ' '.repeat(indent + 2) + objectToJSString(obj[i], indent + 2);
          if (i < obj.length - 1) {
            result += ',';
          }
          result += '\n';
        }
        result += ' '.repeat(indent) + ']';
        return result;
      }

      // 处理普通对象
      const keys = Object.keys(obj);
      if (keys.length === 0) {
        return '{}';
      }

      let result = '{\n';
      for (let i = 0; i < keys.length; i++) {
        const key = keys[i];
        const value = obj[key];

        result += ' '.repeat(indent + 2) +
          `<span class="property">${key}</span>: ` +
          objectToJSString(value, indent + 2);

        if (i < keys.length - 1) {
          result += ',';
        }
        result += '\n';
      }
      result += ' '.repeat(indent) + '}';
      return result;
    }

    // 转义HTML特殊字符
    function escapeHtml(text) {
      return text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#039;');
    }

    // 初始显示提示
    jsOutput.textContent = '// JS对象将在这里显示';
  });
</script>
</body>
</html>